#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ina226.h"
#include "iic.h"
#include "esp_log.h"
#include "freertos/queue.h"
static const char *TAG = "INA226";
float ina226_bus_vol,shunt_vol,ina226_Current;
char Ina226_BusVol_char[] = "no value";
uint16_t config,ID;
#define delay_ms(time)       vTaskDelay(time / portTICK_RATE_MS)
#define ina226_print_switch 1
INA226 ina226_data;
/*定义消息队列*/
xQueueHandle busvol_Gui_queue;
xQueueHandle current_queue;
/*ina226采样电阻为10毫欧*/
//初始化INA226
void mx_ina226_init(void)
{

//	IIC_Init();
    INA226_SendData(INA226_ADDR1,CFG_REG,0x8000);	//重新启动
    INA226_SendData(INA226_ADDR1,CFG_REG,MODE_INA226);
    INA226_SendData(INA226_ADDR1,CAL_REG,CAL);		//设置分辨率
    INA226_Get_ID(INA226_ADDR1);					//获取ina226的id
    INA226_GET_CAL_REG(INA226_ADDR1);
}
/// @brief 
/// @param addr 写芯片地址
/// @param reg 写寄存器地址
/// @param data 写的数据
void INA226_SendData(uint8_t addr,uint8_t reg,uint16_t data)
{
  	uint8_t temp=0,ack;
	IIC_Start();

	IIC_Send_Byte(addr);
	ack = IIC_Wait_Ack();
    //ESP_LOGI(TAG,"sent ack1 = %d \n",ack);//测试INA226是否通讯成功，当数据未成功显示时使用该代码
	IIC_Send_Byte(reg);
	ack = IIC_Wait_Ack();
    //ESP_LOGI(TAG,"sent ack2 = %d \n",ack);
	
	temp = (uint8_t)(data>>8);
	IIC_Send_Byte(temp);
	IIC_Wait_Ack();

	temp = (uint8_t)(data&0x00FF);
	IIC_Send_Byte(temp);
	IIC_Wait_Ack();
	
	IIC_Stop();
}

//设置寄存器指针
//时序注意点1：读取第一个ACK之后最好不要有延时，直接传送寄存器地址
//时序注意点2：SCL保持短时间高电平之后，再读取第二个ACK信号
void INA226_SetRegPointer(uint8_t addr,uint8_t reg)
{
    uint8_t ack;
    SDA_OUT();
	IIC_Start();

	IIC_Send_Byte(addr);
	ack = IIC_Wait_Ack();
    //ESP_LOGI(TAG,"addr ack = %d \n",ack);//经测试这里不能有延时，所以去掉printf
	IIC_Send_Byte(reg);
	ack = IIC_Wait_Ack2();//经测试STM8内的延时增加到50会导致register ack = 1
    //ESP_LOGI(TAG,"register ack = %d \n",ack);

	IIC_Stop();
}

//读取数据
uint16_t INA226_ReadData(uint8_t addr)
{
	uint8_t ack;
    uint16_t temp=0;
	IIC_Start();
        
	IIC_Send_Byte(addr+1);
	ack = IIC_Wait_Ack();
	//ESP_LOGI(TAG,"read ack = %d \n",ack);
	temp = IIC_Read_Byte(1);
	temp<<=8;	
	temp |= IIC_Read_Byte(0);
	IIC_Stop();
	return temp;
}
uint16_t INA226_Read2Byte(uint8_t reg_addr)
{
	uint16_t reg_data=0;
	uint16_t temp=0;
	IIC_Start();
	IIC_Send_Byte(0x80);
	if(IIC_Wait_Ack())return 0;
	IIC_Send_Byte(reg_addr);   
	if(IIC_Wait_Ack())return 0;
	IIC_Start();
	IIC_Send_Byte(0x80);
	if(IIC_Wait_Ack())return 0;
	reg_data= IIC_Read_Byte(1);
	reg_data=(reg_data<<8)&0xFF00;
	temp=IIC_Read_Byte(0);
	IIC_Stop();
	reg_data|=temp;
	return reg_data;
}
/*————————————————
版权声明：本文为CSDN博主「怪都督」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
原文链接：https://blog.csdn.net/weixin_44625313/article/details/113829226
*/
//获取id
void INA226_Get_ID(uint8_t addr)
{
    uint32_t temp=0;
    //手册提到“Read data is from the last register pointer location”
    //所以每次要以Figure25的格式设置寄存器指针才能读取该寄存器的数据
    INA226_SetRegPointer(addr,INA226_GET_ADDR);
    temp = INA226_ReadData(addr);
    ina226_data.ina226_id = temp;
}

//获取校准值
uint16_t INA226_GET_CAL_REG(uint8_t addr)
{
    uint32_t temp=0;
    INA226_SetRegPointer(addr,CAL_REG);
    temp = INA226_ReadData(addr);
    return (uint16_t)temp;
}

//分流电压寄存器01H----------->2.5uV/bit
int16_t INA226_GetShuntVoltage(uint8_t addr)
{
    int16_t temp = 0;
    INA226_SetRegPointer(addr,SV_REG);
    temp = INA226_ReadData(addr);
//	if(temp&0x8000)	temp = ~(temp - 1);
    return (int16_t)temp;
}

//总线电压寄存器02H----------->1.25mV/bit
uint16_t INA226_GetVoltage(uint8_t addr)
{
    uint32_t temp = 0;
    INA226_SetRegPointer(addr,BV_REG);
    temp = INA226_ReadData(addr);
    return (uint16_t)temp;
}

//功率寄存器03H----------->25mW/bit
uint16_t INA226_Get_Power(uint8_t addr)
{
    int16_t temp=0;
    INA226_SetRegPointer(addr,PWR_REG);
    temp = INA226_ReadData(addr);
    return (uint16_t)temp;
}

//电流寄存器04H----------->1mA/bit
int16_t INA226_GetShunt_Current(uint8_t addr)
{
    int16_t temp=0;
    INA226_SetRegPointer(addr,CUR_REG);
    temp = INA226_ReadData(addr);
//	if(temp&0x8000)	temp = ~(temp - 1);
    return temp;
}



//获取分流电压----------->1.18mV/bit
void Get_Shunt_voltage(float *Voltage)//mV
{
    *Voltage = (INA226_GetShuntVoltage(INA226_ADDR1)*INA226_VAL_LSB/1000);//如需矫正电流分流参数请将这里改为2.5
}

//获取总线电压----------->1.25mV/bit
void GetVoltage(float *Voltage)//mV
{
    *Voltage = INA226_GetVoltage(INA226_ADDR1)*Voltage_LSB;
}

//获取功率----------->25mW/bit
void Get_Power(float *Power)//mW
{
    *Power = (INA226_Get_Power(INA226_ADDR1)*POWER_LSB);
}

//获取电流----------->1mA/bit
void Get_Shunt_Current(float *Current)//mA
{
    *Current = (INA226_GetShunt_Current(INA226_ADDR1)* CURRENT_LSB);
}

//获取功率= 总线电压 * 电流
void get_power()//W
{
    GetVoltage(&ina226_data.voltageVal);			//mV
    Get_Shunt_voltage(&ina226_data.Shunt_voltage);	//uV
    Get_Shunt_Current(&ina226_data.Shunt_Current);	//mA
    Get_Power(&ina226_data.Power);					//mW
    ina226_data.Power_Val = ina226_data.voltageVal*0.001f * ina226_data.Shunt_Current*0.001f; //mV*mA
}

//浮点型转字符型函数
char * float2str(float val, int precision, char *buf)
{
    char *cur, *end;
    
    sprintf(buf, "%.6f", val);
    if (precision < 6) {
        cur = buf + strlen(buf) - 1;
        end = cur - 6 + precision; 
        while ((cur > end) && (*cur == '0')) {
            *cur = '\0';
            cur--;
        }
    }
    
    return buf;
}

void ina226_begin(void *pvParameter)
{
    mx_iic_init();
    mx_ina226_init();
    /*初始化消息队列*/
    busvol_Gui_queue = xQueueCreate(1, sizeof(ina226_bus_vol));
    current_queue = xQueueCreate(1, sizeof(ina226_Current));
    while(1)
    {

        INA226_SetRegPointer(0x80,CFG_REG);
        //vTaskDelay(pdMS_TO_TICKS(30)); 
        config = INA226_ReadData(0x80);    
        
        INA226_SetRegPointer(0x80,INA226_GET_ADDR);
        ID = INA226_ReadData(0x80);
       
        GetVoltage(&ina226_bus_vol);
        float2str(ina226_bus_vol,2,Ina226_BusVol_char);//http模块传输字符型
        xQueueSend(busvol_Gui_queue, &ina226_bus_vol, 0);  
        float shunt_vol = 0;
        Get_Shunt_voltage(&shunt_vol);
        // Get_Shunt_Current(&ina226_Current);//!实测使用Get_Shunt_Current函数在实际电流为240ma以下时，测得的电流固定为240ma
        //因此测量电流值由shunt_vol换算后获得
        ina226_Current = shunt_vol/10;
        xQueueSend(current_queue,&ina226_Current,0);
        if (ina226_print_switch)
        {
            // ESP_LOGI(TAG,"CONFIG = %x \n",config);
            // ESP_LOGI(TAG,"INA226_GET_ID = %x\n",ID);
            ESP_LOGI(TAG,"INA226_GET_BUS_VOL = %f\n",ina226_bus_vol);
            ESP_LOGI(TAG,"ina226_Current = %f\n",ina226_Current);
        }
        vTaskDelay(pdMS_TO_TICKS(100)); 
        
    }
    vTaskDelete(NULL);//正常不会执行到这里
    
}